package com.gpio;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

/**
 * @author lotey
 * @date 2017年2月27日 下午3:39:01
 * @desc GPIO控制器线程
 */
public class GPIOControlThread {
	
	private static Logger logger = LogManager.getLogger(GPIOControlThread.class);
	
	private List<Map<String, Object>> list;
	
	//初始化LED灯为正常状态
	public GPIOControlThread(List<Map<String, Object>> list) {
		this.list = list;
		int j=0;
        //初始化路灯
		Map<String, Object> map = null;
        for(int i = 0; i < 30; i++) {
        	map = new HashMap<String, Object>(4);
        	map.put("lightNum", j);
        	map.put("faultType", 4);
			map.put("isIgnore", 0);
			list.add(map);
			j = j + 0x0100;
		}
        this.run(list);
	}
	
	//定义数组存储灯状态
	private static final int light_stat[][] = {
			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},	// 4
			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},

			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},	// 4
			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},

			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},	// 4
			{4,4,4,4,4,4,4,4},	// 0
			{4,4,4,4,4,4,4,4},	// 1
			{4,4,4,4,4,4,4,4},	// 2
			{4,4,4,4,4,4,4,4},	// 3
			{4,4,4,4,4,4,4,4},
		};
	
	//定义GpioPinDigitalOutput对象数组
	private static GpioPinDigitalOutput []gpioPinDigitalOutput = new GpioPinDigitalOutput[5];
	
	//初始化GPIO接口
	static {
		logger.info("======================={}初始化GPIO驱动连接=======================",DateTimeUtil.getCurrentDateTimeStr());
		final GpioController gpio = GpioFactory.getInstance();
        gpioPinDigitalOutput[0] = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_24, "LED0", PinState.LOW);//cs
        gpioPinDigitalOutput[1] = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_25, "LED1", PinState.LOW);//REclk_cen
        gpioPinDigitalOutput[2] = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_27, "LED2", PinState.LOW);//Sdata
        gpioPinDigitalOutput[3] = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_28, "LED3", PinState.LOW);//Sclk
        gpioPinDigitalOutput[4] = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_29, "LED4", PinState.LOW);//REclk_bas
	}
	
	//线程故障设备编号输出流
	private BufferedWriter threadBreakdownWriter = null;
	
	public void run(List<Map<String, Object>> list) {
//		logger.info("======================={}GPIO处理线程开始执行启动=======================",DateTimeUtil.getCurrentDateTimeStr());
		try {
			threadBreakdownWriter = new BufferedWriter(new FileWriter(new File("/home/pi/mqserver/thread-breakdown-equ.txt"),false));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		Map<String, Object> map = null;
		//设备ID
		int lightNum 	= 0;
		//故障类型
		int faultType 	= 0;
		//是否忽略扫描
		int isIgnore 	= 0;
		//设备编号
		String deviceID =null;
		int i			=	0;
		int j			=	0;
		int oper_sel	=	0;
		int light_sel	=	0;
		int ROW 		= 	0;
		int sleep_time	=   1;
		//记录设备编号的16进制，是否异常
		Map<Integer, Integer> equBrokeMap = new HashMap<Integer, Integer>();
		Iterator<Map<String, Object>> ite = list.iterator();
		while (ite.hasNext()) {
			try {
//				logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>{} 当前队列容量大小：{}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",DateTimeUtil.getCurrentDateTimeStr(),list.size());
				map = ite.next();
				//设备ID
				lightNum = (Integer)map.get("lightNum");
				//故障类型
				faultType = (Integer)map.get("faultType");
				//是否忽略扫描
				isIgnore = (Integer)map.get("isIgnore");
				//设备编号
				deviceID = (String)map.get("deviceID");
//				logger.info("======================={}从队列中获取到新消息，deviceID {} lightNum {} faultType {}=======================",DateTimeUtil.getCurrentDateTimeStr(),deviceID,lightNum,faultType);
				i	=	0;
				j	=	0;
				oper_sel	=	lightNum	>>8;
				light_sel	=	lightNum&0x00ff;
				ROW 		= 	oper_sel;
				sleep_time	=10;
				
//				logger.info("=======================参数信息oper_sel {} ; light_sel {} ; ROW {} =======================",oper_sel,light_sel,ROW);
				//如下2种情况都跳过
				//a.lightNum未故障，并且再次进入状态未发生改变
				//b.lightNum已故障，再次进入又变成正常状态，直接跳过，不可将异常状态变回正常状态
				if (1 == isIgnore) {//非初始化
					if (faultType == 1) {
//						logger.info("#########################获取到故障设备信息，设备编号：{} 即将处理#########################",lightNum);
						//将故障设备信息写入文件
						threadBreakdownWriter.write(deviceID + "\n");
						threadBreakdownWriter.flush();
					}
					
//					//检测这两个设备
//					if("371502000000131029".equalsIgnoreCase(deviceID) || "371502000000131036".equalsIgnoreCase(deviceID)) {
//						logger.info("========================设备从故障状态变为正常状态， lightNum ：{} faultType ：{} ========================",lightNum,faultType);
//					}
					
					//跳过部分设备故障信息
					if(faultType == light_stat[ROW][light_sel]) {
//						logger.info("#########################参数信息 退出本次操作，设备编号：{} 状态码：{}#########################",lightNum,faultType);
						continue;
					} else {//状态已发生改变
						if (light_stat[ROW][light_sel] == 1 && faultType == 4) {
							logger.info("========================设备从故障状态变为正常状态，设备编号：{} lightNum ：{}========================",deviceID,lightNum);
						}
						if (equBrokeMap != null && equBrokeMap.containsKey(lightNum)) {
//							logger.info("#########################参数信息 该设备编号已经发生故障 又变回正常直接忽略 退出本次操作，设备编号：{} #########################",lightNum);
							continue;
						}
					}
					
					//存取故障设备信息
					if (faultType == 1) {
						//将故障设备记录，保证每一轮同一故障设备ID出故障后，再次遇到同一故障设备，直接跳过，保证正确性
						equBrokeMap.put(lightNum, faultType);
					}
				}
				
				light_stat[ROW][light_sel]	=	faultType;
				
				gpioPinDigitalOutput[3].low();
				gpioPinDigitalOutput[1].low();	
				gpioPinDigitalOutput[4].low();
				gpioPinDigitalOutput[0].high();
				Thread.sleep( sleep_time);
				//oper_sel	= 0;
				for(i=0;i<5;i++) {
					if((oper_sel &0x10) != 0) {
						gpioPinDigitalOutput[2].high();
					} else {
						gpioPinDigitalOutput[2].low();
					}
					oper_sel = oper_sel<<1;
					Thread.sleep( sleep_time);
					gpioPinDigitalOutput[3].high();
					Thread.sleep( sleep_time);
					gpioPinDigitalOutput[3].low();
					Thread.sleep( sleep_time);
				}
				gpioPinDigitalOutput[1].high();
				Thread.sleep( sleep_time);
				gpioPinDigitalOutput[1].low();
				//完成板选操作
				Thread.sleep( sleep_time);

				for(i=0;i<8;i++) {
					oper_sel	=	light_stat[ROW][i];
					for(j=0;j<3;j++) {
						if((oper_sel &0x04) != 0) {
							gpioPinDigitalOutput[2].high();
						} else {
							gpioPinDigitalOutput[2].low();
						}
						oper_sel = oper_sel<<1;
						Thread.sleep( sleep_time);
						gpioPinDigitalOutput[3].high();
						Thread.sleep( sleep_time);
						gpioPinDigitalOutput[3].low();
						Thread.sleep( sleep_time);
					}
				}
				gpioPinDigitalOutput[4].high();
				Thread.sleep( sleep_time);
				gpioPinDigitalOutput[4].low();
				Thread.sleep( sleep_time);
				gpioPinDigitalOutput[0].low();
				Thread.sleep( sleep_time);
//				if (faultType == 1) {
//					logger.info("======================={}故障设备信息处理完毕，设备编号：{}=======================",DateTimeUtil.getCurrentDateTimeStr(),lightNum);
//				}
				ite.remove();
			}catch(Exception e) {
				logger.error("======================{}控制LED发生异常,详细信息:{}======================",DateTimeUtil.getCurrentDateTimeStr(),e);
				e.printStackTrace();
			} 
		}
		//关闭文件输出流
		try {
			threadBreakdownWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
